from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.generics import GenericAPIView, ListAPIView, RetrieveAPIView, CreateAPIView, ListCreateAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, \
    DestroyModelMixin
from rest_framework.viewsets import ViewSet, GenericViewSet, ReadOnlyModelViewSet, ModelViewSet
from rest_framework import status
from rest_framework.decorators import action
# from django.utils.decorators import method_decorator
from rest_framework.permissions import IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly
from rest_framework.filters import OrderingFilter
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination
from django.db import DatabaseError

from .models import BookInfo, HeroInfo
from .serializers import BookInfoSerializer

"""
利用: GenericViewSet视图集实现查询单一和所有数据接口
"""

class StandardPageNumberPagination(PageNumberPagination):
    """自定义分页类/规则"""
    page_size = 2  # 指定默认每页显示多少条数据 如果前端为指定那就么就用此默认值
    max_page_size = 3  # 前端在指定每页显示多条数据时,最大限制
    page_query_param = 'page'  # 指定前端在控制显示第几页时的查询关键字名字, 默认不写就是page
    page_size_query_param = 'page_size'  # 指定前端在控制显示每页显示多少条数据的查询关键字名字, 默认不写为None


class BookViewSet(ModelViewSet):
    # 指定序列化器
    serializer_class = BookInfoSerializer
    # 指定查询集
    queryset = BookInfo.objects.all()

    # 指定过滤字段
    filter_fields = ['id', 'btitle','bread']

    filter_backends = [OrderingFilter]  # 指定过滤后端为排序过滤
    ordering_fields = ['id', 'bread']  # 指定排序字段

    # 指定分页类/开启分页
    pagination_class = StandardPageNumberPagination




    # IsAuthenticated 表示只有通过认证(登录用户)的用户才能访问此类视图中的所有接口
    permission_classes = [IsAuthenticatedOrReadOnly]  #

    # def get_queryset(self):
    #     if self.action == 'latest':
    #         return BookInfo.objects.all()
    #     else:
    #         return HeroInfo.objects.all()

    # /books/latest/
    @action(methods=['get'], detail=False)
    def latest(self, request):
        """获取最后一本图书"""
        book = BookInfo.objects.latest('id')
        serializer = self.get_serializer(book)

        # raise DatabaseError()

        return Response(serializer.data)

    # /books/pk/update_read/
    @action(methods=['put'], detail=True)
    def update_read(self, request, pk):
        """
        修改图书的阅读量数据
        """
        book = self.get_object()
        book.bread = request.data.get('bread')
        book.save()
        serializer = self.get_serializer(book)
        return Response(serializer.data)





"""
利用: ViewSet视图集实现查询单一和所有数据接口
"""
# class BookViewSet(ViewSet):
#
#     def list(self, request):
#         qs = BookInfo.objects.all()
#         serializer = BookInfoModelSerializer(qs, many=True)
#         return Response(serializer.data)
#
#     def retrieve(self, request, pk):
#         try:
#             book = BookInfo.objects.get(id=pk)
#         except BookInfo.DoesNotExist:
#             return Response(status=status.HTTP_404_NOT_FOUND)
#
#         serializer = BookInfoModelSerializer(book)
#         return Response(serializer.data)



"""
利用:GenericAPIView + mixins 的合成子类来实现标准接口
"""
# class BookListView(ListCreateAPIView):
#     """列表视图"""
#     # 1.指定序列化器类
#     serializer_class = BookInfoModelSerializer
#     # 2.指定查询集
#     queryset = BookInfo.objects.all()
#
#     # def get(self, request, *args, **kwargs):
#     # def get(self, request):
#     #     return self.list(request)
#
#
#
#
# class BookDetailView(RetrieveAPIView):
#     """详情视图"""
#     # 1.指定序列化器类
#     serializer_class = BookInfoModelSerializer
#     # 2.指定查询集
#     queryset = BookInfo.objects.all()





"""
利用:GenericAPIView + mixins扩展来实现获取所有图书和单一图书接口
"""


# class BookListView(CreateModelMixin, ListModelMixin, GenericAPIView):
#     """列表视图"""
#     # 1.指定序列化器类
#     serializer_class = BookInfoModelSerializer
#     # 2.指定查询集
#     queryset = BookInfo.objects.all()
#
#
#     def get(self, request):
#         # # 1. 获取查询集
#         # qs = self.get_queryset()
#         # # 2. 创建序列化器对象进行序列化操作
#         # serializer = self.get_serializer(qs, many=True)
#         # # 3. 响应
#         # return Response(serializer.data)
#         return self.list(request)
#
#     def post(self, request):
#         return self.create(request)
#
#
# class BookDetailView(RetrieveModelMixin, GenericAPIView):
#     """详情视图"""
#     # 1.指定序列化器类
#     serializer_class = BookInfoModelSerializer
#     # 2.指定查询集
#     queryset = BookInfo.objects.all()
#
#
#     def get(self, request, pk):
#         # # 1. 获取到要查询的模型对象
#         # book = self.get_object()
#         # # 2. 创建序列化器进行序列化
#         # serializer = self.get_serializer(book)
#         # # 3. 响应
#         # return Response(serializer.data)
#         return self.retrieve(request)


"""
利用:GenericAPIView 实现查询所有图书及查询指定单一图书的两个接口
"""
# class BookListView(GenericAPIView):
#     """列表视图"""
#     # 1.指定序列化器类
#     serializer_class = BookInfoModelSerializer
#     # 2.指定查询集
#     queryset = BookInfo.objects.all()
#
#     def get(self, request):
#         # 1. 获取查询集
#         qs = self.get_queryset()
#         # 2. 创建序列化器对象进行序列化操作
#         serializer = self.get_serializer(qs, many=True)
#         # 3. 响应
#         return Response(serializer.data)


# class BookDetailView(GenericAPIView):
#
#     # 1.指定序列化器类
#     serializer_class = BookInfoModelSerializer
#     # 2.指定查询集
#     queryset = BookInfo.objects.all()
#
#     """详情视图"""
#     def get(self, request, pk):
#         # 1. 获取到要查询的模型对象
#         book = self.get_object()
#         # 2. 创建序列化器进行序列化
#         serializer = self.get_serializer(book)
#         # 3. 响应
#         return Response(serializer.data)


# 利用DRF中的APIView实现获取所有图书接口
# GET  /books/

# class BookListView(APIView):
#
#     def get(self, request):
#         # 1.获取出查询集
#         qs = BookInfo.objects.all()
#         # 2.创建序列化器进行序列化
#         serializer = BookInfoModelSerializer(qs, many=True)
#
#         # 3.响应 Response
#         return Response(serializer.data)
#
#     def post(self, request):
#         # 1. request.data  获取请求体中的数据
#         data = request.data
#         # 2. 创建序列化器进行反序列化
#         serializer = BookInfoModelSerializer(data=data)
#         # 3. 调用校验方法
#         serializer.is_valid(raise_exception=True)
#         # 4. 调用序列化器的save
#         serializer.save()
#         # 5. 响应
#         return Response(serializer.data)
#
#
# class BookDetailView(APIView):
#
#     def put(self, request, pk):
#         # 1. 获取到要修改的模型对象,如果没有直接响应
#         try:
#             book = BookInfo.objects.get(id=pk)
#         except BookInfo.DoesNotExist:
#             return Response(status=status.HTTP_404_NOT_FOUND)
#         # 2. 获取前端请求数据
#         data = request.data
#         # 3. 创建序列化器进行反序列化(instance=book, data=data)
#         serializer = BookInfoModelSerializer(instance=book, data=data)
#         # 4. 调用校验方法
#         serializer.is_valid(raise_exception=True)
#         # 5. 调用序列化器的save()
#         serializer.save()
#         # 6. 响应
#         return Response(serializer.data)
#
#
#     def delete(self, request, pk):
#         # 获取要删除的模型对象
#         try:
#             book = BookInfo.objects.get(id=pk)
#         except BookInfo.DoesNotExist:
#             return Response(status=status.HTTP_404_NOT_FOUND)
#         # delete()
#         book.delete()
#         # 响应
#         return Response(status=status.HTTP_204_NO_CONTENT)